<?php
/**
 * link: https://www.netbcloud.com/
 * copyright: Copyright (c) 2024 深圳网商天下科技有限公司
 * author: wstianxia
 */

namespace app\forms\common\coze;

use app\forms\common\coze\api\OauthToken;
use app\models\CozeAccount;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use yii\base\BaseObject;
use yii\helpers\Json;

// https://www.coze.cn/docs/developer_guides/api_overview
class ApiForm extends BaseObject
{
    private $apiUrl = 'https://api.coze.cn';
    public $secret;

    /** @var Base */
    public $object;

    /** @var CozeAccount */
    public $account;

    public function init()
    {
        parent::init(); // TODO: Change the autogenerated stub
        if(!$this->secret) {
            if (!$this->account) {
                $this->account = CozeAccount::findOne(['is_delete' => 0]);
            }
            $this->secret = $this->account->coze_secret ?? '';
        }
    }

    public function refreshToken()
    {
        if(!$this->account || $this->account->type == 1){
            return;
        }
        if($this->object instanceof OauthToken){
            return;
        }
        if($this->account->expires_in < time() + 5){
            $object = new OauthToken();
            $object->client_id = $this->account->client_id;
            $object->grant_type = OauthToken::TYPE_REFRESH_TOKEN;
            $object->refresh_token = $this->account->refresh_token;
            $res = (self::common(['secret' => $this->account->client_secret, 'object' => $object]))->request();
            $this->account->isLog = false;
            $this->account->saveOauth($res);
            $this->secret = $this->account->coze_secret ?? '';
        }
    }

    public static function common($config = [])
    {
        return new self($config);
    }

    public function request(){
        try {
            $this->refreshToken();
            if($this->object->getMethod() == Base::METHOD_POST) {
                $res = $this->getClient()
                    ->post($this->apiUrl . $this->object->getMethodName(), [
                        'json' => $this->object->getAttribute(),
                        'headers' => [
                            'Agw-Js-Conv' => 'str',
                            'Authorization' => "Bearer {$this->secret}",
                        ]
                    ]);
            }elseif($this->object->getMethod() == Base::METHOD_UPLOAD) {
                $params = $this->object->getAttribute();
                $res = $this->getClient()
                    ->post($this->apiUrl . $this->object->getMethodName(), [
                        'body' => $params['body'],
                        'headers' => [
                            'Authorization' => "Bearer {$this->secret}",
                            'content-type' => $params['contentType'],
                        ]
                    ]);
            }else{
                $res = $this->getClient()
                    ->get($this->apiUrl . $this->object->getMethodName() .
                        '?' . http_build_query($this->object->getAttribute()),
                        [
                            'headers' => [
                                'Authorization' => "Bearer {$this->secret}",
                            ]
                        ]);
            }
            $body = $res->getBody()->getContents();
        }catch (\Exception $e){
            if ($e instanceof RequestException && $e->hasResponse()) {
                $body = $e->getResponse()->getBody()->getContents();
            }else{
                throw $e;
            }
        }
        return $this->object->response($body ? @Json::decode($body) : ['msg' => '请求异常']);
    }

    private function getClient(): Client
    {
        return new Client(['verify' => \Yii::$app->request->isSecureConnection]);
    }
}
